/*
 * Copyright (C), 2002-2015, 苏宁易购电子商务有限公司
 * FileName: PayDemo.java
 * Author:   15061263
 * Date:     2015-7-13 下午03:52:58
 * Description: //模块目的、功能描述      
 * History: //修改记录
 * <author>      <time>      <version>    <desc>
 * 修改人姓名             修改时间            版本号                  描述
 */
package com.hl.toolkit.server.suning.epp.demo;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.suning.SuNingConfig;
import com.suning.epps.codec.CodecConstants;
import com.suning.epps.codec.Digest;
import com.suning.epps.codec.RSAUtil;
import com.suning.epps.codec.comparator.StringComparator;
import com.util.DateUtils;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang.StringUtils;

import java.security.PublicKey;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.Map.Entry;

/**
 * 〈一句话功能简述〉<br>
 * 〈功能详细描述〉
 * 
 * @author 15061263
 * @see [相关类/方法]（可选）
 * @since 20150713
 */

public class SuningH5Pay {
    /**
     * 私钥
     */
    private static final String PRIVATE_KEY = "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAg"
        + "EAAoGBALb_y4p_Fj3yyaukPXU43h1ZZ3f3MVG2JT5FIxRacHxWarboPPviL4nkZPbU7YNQ8YrAdT"
        + "zfsv8Est6jOxVXwcTplRcnWKe86j_fVH2LwOLjVcT2YMuCq8vk6wqNFrm5FpHs8MToibbrLay0Mh"
        + "PVMDv_QEHL1FSb3jIp2Y185MSXAgMBAAECgYEAq9Dm7hX8cBVwO_NssI7AHJZAi2ZPrAR0W07WbN"
        + "mtG1CXyTurZmMrdzA1i3rHta9d2YRxjsIJcV6cAmUHqDZI-l5SaGUNI5W4uq5tFVenvgNEvYQsRz"
        + "JWPfYtkFCgXG38CNu-v8G3lEbptxUa8jfBhYDYsqyAFuktY8eILfmqaOECQQDZ8brK_ANYVKeXy2"
        + "eeYz8uikr_JCpTRbwc4_BPOuGQ604GhY3CqvHh5heJbZUnYjJRZh-P7QkJ67cEqQe2E_yVAkEA1v"
        + "P-0dzlv_I83q1ECdXV_C0tRtwxfdNDeAhoJjD-7CPqFeH5FsMi1d1u7eI0A0cmtYgKv1yfOQ_3Wv"
        + "4TPY2FewJAFjiZTPzo8mafN9DbXcDMvlgHUYBEeH0RsvhilhFw0i_LosqXK5P2WYv2NmLf5EYUz0"
        + "vUR_5o_4PzAxyg1qWvCQJBANSK2rJkfAC545pDNP2MpVP-z8A7ReymkxYDKghpdgfE01fj40qwlK"
        + "dnlqI9gzSijBH_fLEPQplHwkwE4r2ATDUCQQDMJmDsuubnHNUADCDin6NR9cyQRK1Y1QNuhK6xU_"
        + "vEUTRMY9BkHJGXo1hQHirH5sr6Y8K3zx7cYgbKiyUG1IgX"; 
    private static PayProperties prop = new PayProperties(); 

    public static void main(String[] args) throws Throwable {
        Map<String, String> requestMap = new HashMap<String, String>();
        //StringBuilder orderData = new StringBuilder();
        //测试地址
       String url = "http://paytestpre.suning.com/epps-pprg/routeGateway/merchant/paymentOrder.htm";
       // String url="https://wpaysandbox.suning.com/epps-pwg/routeGateway/merchant/paymentOrder.htm";
        requestMap.put("merchantNo", SuNingConfig.DemomerchantNo);
        requestMap.put("merchantDomain", "");
        requestMap.put("publicKeyIndex", "0001");
        requestMap.put("signAlgorithm", "RSA");
        requestMap.put("inputCharset", "UTF-8");
        requestMap.put("notifyUrl", "http://api.test.suning.com/atinterface/receive_return.htm");
        requestMap.put("returnUrl", "http://api.test.suning.com/atinterface/receive_return.htm");
        requestMap.put("submitTime", new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()));
        requestMap.put("buyerIp", "");
        requestMap.put("buyerUserNo", "");
        requestMap.put("buyerMerchantNo", "");
        requestMap.put("buyerAlias", "");
        requestMap.put("buyerMerchantLoginName", "");
        requestMap.put("buyerMerchantUserNo", "");
        requestMap.put("orders", getOrders(requestMap));
        requestMap.put("signature", generateSignature(requestMap));
     //    打印最终url
        System.out.println(mosaicUrlWithParams(url, requestMap));
        StringBuffer formParamters = new StringBuffer();
        for (Entry<String, String> entry : requestMap.entrySet()) {
            formParamters.append(buildInputHiddenFieldInForm(entry.getKey(), entry.getValue()));
        }
        String formString = buildForm(url, formParamters.toString());
        // 打印最终提交的form表单
        System.out.println("PC下单请求form表单：" + formString);
        String testStr = "退货后退款";
        System.out.println(base64Encode(testStr));
        Double dValue = Double.parseDouble("31.5")*100;

        System.out.println(String.valueOf(dValue.longValue()));
    }

    public static String buildRequest(Map<String, String> pageMap) throws Throwable {
        Map<String, String> requestMap = new HashMap<String, String>();
          DateUtils.formatDateTime3(new Date()) ;
         String submitTime=new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
      requestMap.put("merchantNo",SuNingConfig.merchantNo);
      //  requestMap.put("merchantNo", prop.getString("merchantNo"));
        requestMap.put("merchantDomain", "");
        requestMap.put("publicKeyIndex", "0001");
        requestMap.put("signAlgorithm", "RSA");
        requestMap.put("inputCharset", "UTF-8");
        requestMap.put("notifyUrl", SuNingConfig.applicationH5NotiyReturnUrl);
        requestMap.put("returnUrl", SuNingConfig.applicationSystemSuccessUrl);
        requestMap.put("submitTime", submitTime);
        requestMap.put("buyerIp", "");
        requestMap.put("buyerUserNo", "");
        requestMap.put("buyerMerchantNo", SuNingConfig.merchantNo);
        requestMap.put("buyerAlias", "test123@163.com");
      //  requestMap.put("buyerMerchantLoginName", pageMap.get("buyerMerchantLoginName"));
      //  requestMap.put("buyerMerchantUserNo", pageMap.get("buyerMerchantUserNo"));
        requestMap.put("orders", getOrders(pageMap));
        requestMap.put("version", "1.0");
        requestMap.put("signature", generateSignature(requestMap));

        // 打印最终url
        System.out.println(mosaicUrlWithParams(SuNingConfig.demoOrderUrl, requestMap));
        StringBuffer formParamters = new StringBuffer();
        for (Entry<String, String> entry : requestMap.entrySet()) {
            formParamters.append(buildInputHiddenFieldInForm(entry.getKey(), entry.getValue()));
        }
        //System.out.println("formParamters====" + formParamters);
        String formString = buildForm(SuNingConfig.demoOrderUrl, formParamters.toString());
        // 打印最终提交的form表单
        System.out.println("PC下单请求form表单：" + formString);
        return formString;
    }

    /**
     * 
     * 功能描述: <br>
     * 生成订单orders
     * 
     * @param orderData
     * @return
     * @throws Throwable
     * @see [相关类/方法](可选)
     * @since 20150325
     */
    public static String getOrders(Map<String, String> requestMap) throws Throwable {
    	//StringBuilder orderData = new StringBuilder();
        ArrayList<HashMap<String, String>> orderList = new ArrayList<HashMap<String, String>>();
        Map<String, String> order = new HashMap<String, String>();
        Random random = new Random();
        String merchantOrderNo = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + random.nextInt(99999);
    	String outOrderNo=requestMap.get("outOrderNo");
    	
    	String  body=requestMap.get("body");
    	String  goodsName=requestMap.get("goodsName");
    	String  price=requestMap.get("price");
    	
        for (int i = 0; i < 1; i++) {
            //Map<String, String> orderInfos = new HashMap<String, String>();
            order.put("salerUserNo", "");
          order.put("salerMerchantNo", SuNingConfig.merchantNo);
          //   order.put("salerMerchantNo", prop.getString("salerMerchantNo"));

            order.put("salerAlias", "");
            order.put("royaltyParameters", "");
            order.put("orderType", "01");
            order.put("outOrderNo", outOrderNo);
            System.out.println("outOrderNo====" + outOrderNo);
            order.put("merchantOrderNo", merchantOrderNo);
            order.put("goodsName", base64Encode(goodsName));
            order.put("goodsType", "011001");
            order.put("body",base64Encode(body));
            order.put("showUrl", "http://product.suning.com/123768362.html");
            order.put("receiveInfo", base64Encode("张三|江苏省南京市|210000|13222222222"));
            order.put("price", price);
            //商品金额转化成分
            Double dValue = Double.parseDouble(requestMap.get("orderAmount"))*100;
            order.put("orderAmount", String.valueOf(dValue.longValue()));
            order.put("quantity", "1");
            order.put("currency", "CNY");
            Date orderTime = new Date();
            order.put("orderTime", new SimpleDateFormat("yyyyMMddHHmmss").format(orderTime));
            //order.put("depositOrderTime", "20150720162045");
            //order.put("depositOrderTime", new SimpleDateFormat("yyyyMMddHHmmss").format(orderTime));
            //order.put("orderFlag", "01");
            order.put("payTimeout", "1h");
            order.put("tunnelData", base64Encode("{”aa”:”bb”}"));
            orderList.add((HashMap<String, String>) order);
        }

        String orders = JSON.toJSONString(orderList, SerializerFeature.DisableCircularReferenceDetect);
        return orders;
    }

    public static TreeMap<String, String> treeMap(Map<String, String> map, String... keys) {
        // 初始化字符串比较器
        Comparator<String> stringComparator = new StringComparator();

        TreeMap<String, String> treeMap = new TreeMap<String, String>(stringComparator);
        treeMap.putAll(map);
        // 移除非摘要的key
        for (String key : keys) {
            treeMap.remove(key);
        }
        return treeMap;
    }
    
    /**
     * 
     * 功能描述: <br>
     * 将map转成a1=b1&a2=b2&a3=b3形式的字符串
     * 
     * @param map
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static String mapToString(Map<String, String> map) {
        StringBuilder result = new StringBuilder();
        for (Entry<String, String> entry : map.entrySet()) {
            String value = entry.getValue()==null?"": entry.getValue().trim();
            result.append(entry.getKey()).append(CodecConstants.EQ_SYMBOL).append(value).append(CodecConstants.AND_SYMBOL);
        }
        if (result.length() > 0) {
            result.deleteCharAt(result.length() - 1);
        }
        return result.toString().trim();
    }
    
    /**
     * 
     * 功能描述: <br>
     * 生成签名
     * 
     * @param requestMap
     * @return
     * @see [相关类/方法](可选)
     * @since 20150325
     */
    public static String generateSignature(Map<String, String> requestMap) {
        System.out.println("开始生成签名");
        List<String> excudeKeylist = new ArrayList<String>();
        excudeKeylist.add("signature");
        excudeKeylist.add("signAlgorithm");
        String[] excudeKey = new String[excudeKeylist.size()];
        TreeMap<String, String> treeMap = treeMap(requestMap, excudeKeylist.toArray(excudeKey));
        System.out.println("生成摘要的字符串：" + mapToString(treeMap));
        String digest = Digest.digest(requestMap, excudeKeylist.toArray(excudeKey));
        System.out.println("digest : " + digest);
        String sign = null;
        try {
 
            sign = RSAUtil.sign(digest,  RSAUtil.resolvePrivateKey("D:/RSA/private.key"));
          //  sign = RSAUtil.sign(digest, RSAUtil.getPrivateKey(PRIVATE_KEY));

        } catch (Throwable e) {
            System.err.println("生成签名失败");
            e.printStackTrace();
        }
        System.out.println("requestMap====" + requestMap);
        System.out.println("sign : " + sign);
        return sign;
        //return "C_OWo1PkvCWddVRO98WlDTjiPZ9vGVCjOqL4pxE7on_45ciOtp4RYeMfS2bfwTY0Z6Q_rNSgvfI4yVUs-09evv8fbKayYUJYOAcd0gefSZvMZ-4QAxftBrgDSnJan9Zdscs635UkjUum16gguND7JiWtGbymGt_j2QwWv9HU_hI";
    }

    /**
     * 
     * 功能描述: <br>
     * base 64 编码
     * 
     * @param str
     * @return
     * @since 20150325
     */
    public static String base64Encode(String str) {
        byte[] encodeBase64 = null;
        String result = null;
        if (StringUtils.isEmpty(str)) {
            return str;
        }
        try {
            encodeBase64 = Base64.encodeBase64(str.getBytes("UTF-8"));
            result = new String(encodeBase64, "UTF-8");
        } catch (Throwable e) {
            System.err.println("Base64失败");
        }

        return result;
    }

    public static String mosaicUrlWithParams(String url, Map<String, String> params) {
        StringBuilder paramStr = new StringBuilder();
        for (Entry<String, String> entry : params.entrySet()) {
            paramStr.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
        }
        return url + "?" + paramStr.substring(0, paramStr.length() - 1);

    }
    
    /**
     * This method gets hidden type HTML element using passed name and value.
     * 
     * @param paramName
     * @param paramValue
     * @return
     */
    private static String buildInputHiddenFieldInForm(String paramName, String paramValue) {
        String line = "<input type=\"hidden\" name=\"\" value=\"\">";
        if (paramName == null || paramValue == null) {
            return "";
        } else {
        	paramValue = paramValue.replaceAll("\"", "&quot;");
            int nameSize = "name=".length() + 1;
            int valueSize = "value=".length() + 1;
            line = line.substring(0, line.indexOf("name=") + nameSize) + paramName
                    + line.substring(line.indexOf("name") + nameSize);
            line = line.substring(0, line.indexOf("value=") + valueSize) + paramValue
                    + line.substring(line.indexOf("value=") + valueSize);
            return line;
        }
    }
    
    /**
     * 拼装form表单
     * 
     * @return
     */
    private static String buildForm(String url, String inputFiled) {

        StringBuffer form = new StringBuffer();
        form.append("<form name=\"punchout_form\" method=\"post\" action=\"");
        form.append(url);
        form.append("\">");
        form.append(inputFiled);
        form.append("</form>");
        form.append("<input type=\"submit\" value=\"确认\" style=\"display:none;\"></form>");
        //form.append("<script>alert(document.forms[0].orders.value);</script>");
        form.append("<script>document.forms['punchout_form'].submit();</script>");
        return form.toString();
    }
    
    /**
     * 
     * 功能描述: <br>
     * 对数据进行验签 1.对Base64公钥进行解码 2.数据验签
     * 
     * @param signData
     * @param signature
     * @param publicKey
     * @return
     * @throws Exception
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static boolean verifySignature(Map<String, String> requestMap, String signature, String publicKey) throws Exception {
    	System.out.println("开始生成易付宝通知摘要");
        List<String> excudeKeylist = new ArrayList<String>();
        excudeKeylist.add("signature");
        excudeKeylist.add("signAlgorithm");
        String[] excudeKey = new String[excudeKeylist.size()];
        TreeMap<String, String> treeMap = treeMap(requestMap, excudeKeylist.toArray(excudeKey));
        System.out.println("生成易付宝通知摘要的字符串：" + mapToString(treeMap));
        String signData = Digest.digest(requestMap, excudeKeylist.toArray(excudeKey));
        System.out.println("digest : " + signData);
    	// 参数检查
        if (signData == null || signData.length() == 0) {
            throw new Exception("原数据字符串为空");
        }
        if (signature == null || signature.length() == 0) {
            throw new Exception("签名字符串为空");
        }
        if (publicKey == null || publicKey.length() == 0) {
            throw new Exception("公钥字符串为空");
        }
        try {
            // 获取根据公钥字符串获取私钥
            PublicKey pubKey = RSAUtil.getPublicKey(publicKey);
            // 返回验证结果
            return RSAUtil.vertiy(signData, signature, pubKey);
        } catch (Exception e) {
            throw new Exception("验证签名异常", e);
        }
    }
}
